/* -*- c++ -*- */

#ifndef _LINEA_H_
#define _LINEA_H_
#include "defs.h"
#include "Punto.h"

#define TN1    0
#define TN2    1
#define TN12   2

class Linea {
 private:
  int _nodes[ TN12];
  int _num;
 public:
  Linea( int n1, int n2 = 0, int num = 0) {
    _nodes[ TN1] = n1;
    _nodes[ TN2] = n2;
    _num = num;
  };
  Linea( const Linea &tr) {
    _nodes[ TN1] = tr._nodes[ TN1];
    _nodes[ TN2] = tr._nodes[ TN2];
    _num = tr._num;
  }
  Linea( void){};
  ~Linea() {};

  Linea &operator=( const Linea &tr) {
    _nodes[ TN1] = tr._nodes[ TN1];
    _nodes[ TN2] = tr._nodes[ TN2];
    _num = tr._num;
    return *this;
  }
  
  void set( int n1, int n2 = 0, int num = 0) {
    _nodes[ TN1] = n1;
    _nodes[ TN2] = n2;
    _num = num;
  };
  
  void set_min_first( int n1, int n2 = 0, int num = 0) {
    if ( n1 <= n2) {
      _nodes[ TN1] = n1;
      _nodes[ TN2] = n2;
    } else {
      _nodes[ TN1] = n2;
      _nodes[ TN2] = n1;
    }
    _num = num;
  };
  int get_num() const { return _num; }
  void set_num( int num) {
    _num = num;
  }
  void add_num( int num) {
    _num += num;
  }

  int v1( void) const { return _nodes[ TN1];}
  int v2( void) const { return _nodes[ TN2];}
  int v( int idx) const { return _nodes[ idx];}
  int num( void) const { return _num;}

  int vmin( void) const {
    int ret = _nodes[ TN1];
    if ( _nodes[ TN2] < ret) ret = _nodes[ TN2];
    return ret;
  }
  
  int vmax( void) const {
    int ret = _nodes[ TN1];
    if ( _nodes[ TN2] > ret) ret = _nodes[ TN2];
    return ret;
  }

  // Punto get_normal( const Punto *coords) const {
  //   Punto normal;
  //   Punto u, v;
  //   u = coords[ _nodes[ TN2]] - coords[ _nodes[ TN1]];
  //   v = coords[ _nodes[ TN3]] - coords[ _nodes[ TN1]];
  //   double x = u.y() * v.z() - u.z() * v.y();
  //   double y = u.z() * v.x() - u.x() * v.z();
  //   double z = u.x() * v.y() - u.y() * v.x();
  //   normal.set( ( float)x, ( float)y, ( float)z);
  //   normal.normalize();
  //   return normal;
  // }

  void swap_sense() {
    int tmp = _nodes[ TN2];
    _nodes[ TN2] = _nodes[ TN1];
    _nodes[ TN1] = tmp;
  }
  
  // void get_plane( const Punto *coords, float &a, float &b, float &c, float &d) const {
  //   Punto normal = get_normal( coords);
  //   const Punto &p1 = coords[ _nodes[ TN1]];
  //   float dd = - ( normal * p1);
  //   a = normal.x();
  //   b = normal.y();
  //   c = normal.z();
  //   d = dd;
  // }
  // 
  // float get_plane( const Punto *coords, Punto &v) {
  //   v = get_normal( coords);
  //   const Punto &p1 = coords[ _nodes[ TN1]];
  //   float dd = - ( v * p1);
  //   return dd;
  // }
  // 
  // CPUfloat4 get_plane( const Punto *coords) {
  //   Punto v = get_normal( coords);
  //   const Punto &p1 = coords[ _nodes[ TN1]];
  //   float d = - ( v * p1);
  //   CPUfloat4 plano( v, d);
  //   return plano;
  // }


  int esta_colapsado( void) const {
    return ( _nodes[ TN1] == _nodes[ TN2]);
  }
  
  int no_esta_colapsado( void) const {
    return ( _nodes[ TN1] != _nodes[ TN2]);
  }
};

inline int qsort_linea_min_max( const void *v1, const void *v2) {
  Linea *l1 = ( Linea *)v1;
  Linea *l2 = ( Linea *)v2;
  int dif = l1->vmin() - l2->vmin();
  if ( !dif) {
    dif = l1->vmax() - l2->vmax();
  }
  return ( dif > 0) - ( dif < 0); // -1, 0 or +1
}

inline int qsort_linea_n1_n2( const void *v1, const void *v2) {
  Linea *l1 = ( Linea *)v1;
  Linea *l2 = ( Linea *)v2;
  int dif = l1->v1() - l2->v1();
  if ( !dif) {
    dif = l1->v2() - l2->v2();
  }
  return ( dif > 0) - ( dif < 0); // -1, 0 or +1
}

inline int qsort_linea_num( const void *v1, const void *v2) {
  Linea *l1 = ( Linea *)v1;
  Linea *l2 = ( Linea *)v2;
  int dif = l1->num() - l2->num();
  return ( dif > 0) - ( dif < 0); // -1, 0 or +1
}

inline bool equal_nodes( const Linea &l1, const Linea &l2) {
  return ( l1.v1() == l2.v1()) && ( l1.v2() == l2.v2());
}

#endif // _LINEA_H_
